using System;
using System.Web.Compilation;
using System.Resources;
using System.Reflection;
using System.Globalization;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Collections.Specialized;

namespace Infrastructure.CrossCutting.Resource
{
    /// <summary>
    /// Resource provider accessing resources from the database.
    /// This type is thread safe.
    /// </summary>
    public class DBResourceProvider : DisposableBaseType, IResourceProvider
    {
        private readonly IDBResourceSerivce _dbResourceSerivce;

        // resource cache
        private readonly static Dictionary<string, Dictionary<string, string>> ResourceCache = new Dictionary<string, Dictionary<string, string>>();

        public DBResourceProvider(string classKey,IDBResourceSerivce dbResourceSerivce)
        {
            _dbResourceSerivce = dbResourceSerivce;
        }
        #region IResourceProvider Members
        public object GetObject(string resourceKey, System.Globalization.CultureInfo culture)
        {
            if (Disposed)
            {
                throw new ObjectDisposedException("DBResourceProvider object is already disposed.");
            }
            if (string.IsNullOrEmpty(resourceKey))
            {
                throw new ArgumentNullException("resourceKey");
            }

            if (culture == null)
            {
                culture = CultureInfo.CurrentUICulture;
            }
            string resourceValue = null;
            Dictionary<string, string> resCacheByCulture = null;
           
            if (ResourceCache.ContainsKey(culture.Name))
            {
                resCacheByCulture = ResourceCache[culture.Name];
                if (resCacheByCulture.ContainsKey(resourceKey))
                {
                    resourceValue = resCacheByCulture[resourceKey];
                }
            }

            // if not in the cache, go to the database
            if (resourceValue == null)
            {
                resourceValue = _dbResourceSerivce.GetResourceByCultureAndKey(culture, resourceKey);
                // add this result to the cache
                // find the dictionary for this culture
                // add this key/value pair to the inner dictionary
                lock (this)
                {
                    if (resCacheByCulture == null)
                    {
                        resCacheByCulture = new Dictionary<string, string>();
                        ResourceCache.Add(culture.Name, resCacheByCulture);
                    }
                    resCacheByCulture.Add(resourceKey, resourceValue);
                }
            }
            return resourceValue;
        }

        /// <summary>
        /// Returns a resource reader.
        /// </summary>
        public System.Resources.IResourceReader ResourceReader
        {
            get
            {
                if (Disposed)
                {
                    throw new ObjectDisposedException("DBResourceProvider object is already disposed.");
                }

                // this is required for implicit resources 
                // this is also used for the expression editor sheet 

                ListDictionary resourceDictionary = _dbResourceSerivce.GetResourcesByCulture(CultureInfo.InvariantCulture);
                return new DBResourceReader(resourceDictionary);
            }

        }

        #endregion

        protected override void Cleanup()
        {
            try
            {
                this._dbResourceSerivce.Dispose();
            }
            finally
            {
                base.Cleanup();
            }
        }

    }
}